/*
 * Copyright (C) 2013 ePapyrus, Inc. All rights reserved.
 *
 * This file is part of the PlugPDF Android project.
 */

/*
 * SimpleReaderControlView.java
 *
 * Version:
 *       id
 *
 * Revision:
 *      logs
 */

package com.epapyrus.plugpdf;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.LruCache;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.ViewFlipper;

import com.epapyrus.plugpdf.SimpleReaderControlPanel.PanelType;
import com.epapyrus.plugpdf.core.BaseReaderControl;
import com.epapyrus.plugpdf.core.PlugPDF;
import com.epapyrus.plugpdf.core.PlugPDFUtility;
import com.epapyrus.plugpdf.core.annotation.tool.AnnotSetting;
import com.epapyrus.plugpdf.core.annotation.tool.AnnotToolSelect;
import com.epapyrus.plugpdf.core.annotation.tool.BaseAnnotTool;
import com.epapyrus.plugpdf.core.annotation.tool.BaseAnnotTool.AnnotToolType;
import com.epapyrus.plugpdf.core.gesture.BaseGestureProcessor.GestureType;
import com.epapyrus.plugpdf.core.viewer.BasePlugPDFDisplay.PageDisplayMode;

import java.util.List;

/**
 * Menu control built-in class.
 * This is the UI processing class with several PDF operations to be displayed to the user.
 *
 * @author ePapyrus
 * @see <a href="http://www.plugpdf.com">http://www.plugpdf.com</a>
 */
public class SimpleReaderControlView extends RelativeLayout {

	private BaseReaderControl mController;
	private SimpleReaderControlPanel mControlPanel;
	private AnnotSettingMenu mAnnotSettingMenu;
	private AnnotToolSelectMenu mAnnotToolSelectMenu;
	Activity mAct;

	private boolean mButtonsVisible;
	private boolean mTopBarIsSearch;

	private ViewFlipper mTopBarSwitcher;
	private Button mSearchButton;

	// search
	private EditText mSearchText;

	// edit
	private Button mEditCancelButton;
	private Button mEditNoteButton;
	private Button mEditInkButton;
	private Button mEditEraserButton;
	private Button mEditHighlightButton;
	private Button mEditUnderlineButton;
	private Button mEditStrikeoutButton;
	private Button mAnnotToolSelectButton;


	private Button mAnnotSettingCancelButton;
	private ImageView mAnnotSettingColorPickerButton;
	private Button mAnnotSettingAnnotSelectButton;

	private boolean enableHiddenTopBar;
	private boolean enableHiddenBottomBar;

	private Point mDiviceSize;
	private int mNumberOfPreView = 0;
	private AnnotToolType mAnnotToolType;

	private TextView pageText;
	private ListView listview;
	private ThumbnailAdapter adapter;
	private List<Bitmap> thumbnailList;
	/**
	 * Constructor.
	 *
	 * @param context {@link Context} instance
	 */
	public SimpleReaderControlView(Context context) {
		super(context);
	}

	/**
	 * Constructor.
	 *
	 * @param context  {@link Context} instance
	 * @param attrs    {@link AttributeSet}
	 */
	public SimpleReaderControlView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	/**
	 * Creates the UI layout.
	 *
	 * @param controller Object of {@link BaseReaderControl} class
	 */
	public void createUILayout(BaseReaderControl controller) {

		mController = controller;
		pageText = (TextView) findViewById(R.id.page_text);
		mTopBarSwitcher = (ViewFlipper) findViewById(R.id.flipper);

		mSearchButton = (Button) findViewById(R.id.rc_search);
		mSearchText = (EditText) findViewById(R.id.rc_search_text);
		mEditCancelButton = (Button) findViewById(R.id.rc_edit_cancel);
		mEditNoteButton = (Button) findViewById(R.id.rc_edit_note);
		mEditInkButton = (Button) findViewById(R.id.rc_edit_ink);
		mEditEraserButton = (Button) findViewById(R.id.rc_edit_eraser);
		mEditHighlightButton = (Button) findViewById(R.id.rc_edit_tm_highlight);
		mEditUnderlineButton = (Button) findViewById(R.id.rc_edit_tm_underline);
		mEditStrikeoutButton = (Button) findViewById(R.id.rc_edit_tm_strikeout);
		mAnnotToolSelectButton = (Button) findViewById(R.id.rc_annot_tool_select);
		mAnnotSettingCancelButton = (Button) findViewById(R.id.tool_select_cancel);
		mAnnotSettingColorPickerButton = (ImageView) findViewById(R.id.current_color_picker);
		mAnnotSettingAnnotSelectButton = (Button) findViewById(R.id.annot_tool_select);

		listview = (ListView) findViewById(R.id.listview);
	}

	/**
	 * Initializes the UI components of the PDF document viewer.
	 *
	 * @param act {@link Activity}
	 */
	public void init(Activity act, List<Bitmap> list) {

		mAct = act;
		thumbnailList = list;
		mAnnotSettingMenu = new AnnotSettingMenu(getContext());
		mAnnotToolSelectMenu = new AnnotToolSelectMenu(getContext());

		mControlPanel = new SimpleReaderControlPanel(getContext(), this,
				mController);
		showOutlineButton(true);

		setEnableHiddenTopBar(false);
		setEnableHiddenBottomBar(false);
		mTopBarSwitcher.setVisibility(View.INVISIBLE);

		mSearchButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				//searchModeOn();
				mController.search(mSearchText.getText().toString(), 1);
			}
		});


		mSearchText.addTextChangedListener(new TextWatcher() {

			public void afterTextChanged(Editable s) {
				boolean haveText = s.toString().length() > 0;

				mController.resetSearchInfo();
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
										  int after) {
			}

			public void onTextChanged(CharSequence s, int start, int before,
									  int count) {
			}
		});

		mSearchText
				.setOnEditorActionListener(new TextView.OnEditorActionListener() {
					public boolean onEditorAction(TextView v, int actionId,
												  KeyEvent event) {
						if (actionId == EditorInfo.IME_ACTION_NEXT
								|| actionId == EditorInfo.IME_ACTION_DONE) {
							mController.search(
									mSearchText.getText().toString(), 1);
						}
						return false;
					}
				});


		mEditCancelButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				editModeOff();
				mController.changeGestureType(GestureType.VIEW);
			}
		});

		mEditNoteButton.setOnClickListener(mEditButtonClickHandler);
		mEditInkButton.setOnClickListener(mEditButtonClickHandler);
		mEditEraserButton.setOnClickListener(mEditButtonClickHandler);
		mEditHighlightButton.setOnClickListener(mEditButtonClickHandler);
		mEditUnderlineButton.setOnClickListener(mEditButtonClickHandler);
		mEditStrikeoutButton.setOnClickListener(mEditButtonClickHandler);
		mAnnotToolSelectButton.setOnClickListener(mEditButtonClickHandler);

		mAnnotSettingCancelButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				setAnnotSettingMode(false);
			}
		});
		mAnnotSettingColorPickerButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mAnnotSettingMenu.show(v, 0, 0, mAnnotToolType);
				mAnnotSettingMenu.getPopupWindow().setOnDismissListener(new PopupWindow.OnDismissListener() {
					@Override
					public void onDismiss() {
						((GradientDrawable) mAnnotSettingColorPickerButton.getBackground()).setColor(0xff000000 + AnnotSetting.instance().getLineColor(mAnnotToolType));
					}
				});
			}
		});

		mAnnotSettingAnnotSelectButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mAnnotToolSelectMenu.show(v, 0, 0);
			}
		});

		Display display = mAct.getWindowManager().getDefaultDisplay();
		mDiviceSize = new Point();
		display.getSize(mDiviceSize);
		mAnnotToolType = AnnotToolType.NONE;

		mAnnotToolSelectMenu.setAnnotToolSelectedListener(new OnAnnotToolSelectedListener() {
			@Override
			public void ToolSelected(AnnotToolType toolType) {
				setAnnotSettingMode(false);
				mAnnotToolType = toolType;
				setAnnotSettingMode(true);
			}
		});

		adapter = new ThumbnailAdapter(mAct,thumbnailList);
		listview.setAdapter(adapter);


		listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				Intent intent = new Intent();
				intent.setAction("com.hyzh.pdfview.pdfreader");// 发送广播 ，通知上一个界面更新程序
				intent.putExtra("index", position);// 照片list的下标
				LocalBroadcastManager.getInstance(mAct).sendBroadcast(intent);
				listview.smoothScrollToPositionFromTop(position,0);
			}
		});
	}

	/**
	 * Sets the title.
	 *
	 * @param title {@link String} value to set the title
	 */
	public void setTitle(String title) {
		//mTitle.setText(title);
	}

	/**
	 * The top menu show/hide.
	 * @param isTextFieldFocused If the values is ture, do not hide top menu.
	 */
	public void toggleControlTabBar(boolean isTextFieldFocused) {
		if (!mButtonsVisible)
			show();
		else
		if(!isTextFieldFocused) hideTopMenu();
	}


	/**
	 * Refreshes the layout.
	 */
	public void refreshLayout() {
		mControlPanel.refreshLayout();
	}

	/**
	 * Shows the top menu.
	 */
	public void show() {
		if (mButtonsVisible)
			return;

		mButtonsVisible = true;

		if (mTopBarIsSearch) {
			mSearchText.requestFocus();
			showKeyboard();
		}
		if (!isEnableHiddenTopBar()) {
			Animation anim = new TranslateAnimation(-mTopBarSwitcher.getWidth(), 0,
					0, 0);
			anim.setDuration(200);
			anim.setAnimationListener(new Animation.AnimationListener() {
				public void onAnimationStart(Animation animation) {
					mTopBarSwitcher.setVisibility(View.VISIBLE);
				}

				public void onAnimationRepeat(Animation animation) {
				}

				public void onAnimationEnd(Animation animation) {
				}
			});
			mTopBarSwitcher.startAnimation(anim);
		}
	}


	/**
	 * Hides the top menu.
	 */
	public void hideTopMenu() {
		if (!mButtonsVisible)
			return;
		mButtonsVisible = false;

		hideKeyboard();
		if (!isEnableHiddenTopBar()) {
			Animation anim = new TranslateAnimation(0, -mTopBarSwitcher.getWidth(), 0,
					0);
			anim.setDuration(200);
			anim.setAnimationListener(new Animation.AnimationListener() {
				public void onAnimationStart(Animation animation) {
				}

				public void onAnimationRepeat(Animation animation) {
				}

				public void onAnimationEnd(Animation animation) {
					mTopBarSwitcher.setVisibility(View.INVISIBLE);
				}
			});
			mTopBarSwitcher.startAnimation(anim);
		}

	}

	private AsyncTask<Void,Integer,Void> prevFetchTask;

	public void updatePageNumber(int pageIdx, int pageCount){
		pageText.setText(pageIdx + "/" + pageCount);
	}


	/**
	 * Sets the search mode.
	 *
	 * @param on {@link Boolean} value to set the search mode.
	 */
	private void setSearchMode(boolean on) {
		if (on) {
			mTopBarSwitcher.showNext();
		} else {
			mTopBarSwitcher.showPrevious();
		}
	}

	/**
	 * Enables the search mode.
	 */
	void searchModeOn() {
		mTopBarIsSearch = true;
		mSearchText.requestFocus();
		showKeyboard();
		setSearchMode(true);
	}

	/**
	 * Disables the search mode.
	 */
	void searchModeOff() {
		mTopBarIsSearch = false;
		hideKeyboard();
		setSearchMode(false);
		mController.resetSearchInfo();
	}

	/**
	 * Shows the keyboard.
	 */
	void showKeyboard() {
		InputMethodManager imm = (InputMethodManager) getContext()
				.getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm != null) {
			imm.showSoftInput(mSearchText, 0);
		}
	}

	/**
	 * Hides the keyboard.
	 */
	void hideKeyboard() {
		InputMethodManager imm = (InputMethodManager) getContext()
				.getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm != null) {
			imm.hideSoftInputFromWindow(mSearchText.getWindowToken(), 0);
		}
	}

	/**
	 * Opens/closes the edit mode.
	 *
	 * @param on {@link Boolean} value to set the edit mode.
	 */
	private void setEditMode(boolean on) {
		if (on) {
			mTopBarSwitcher.showNext();
			mTopBarSwitcher.showNext();
		} else {
			mTopBarSwitcher.showPrevious();
			mTopBarSwitcher.showPrevious();
		}
	}

	/**
	 * Opens/closes the annotaion's setting mode.
	 *
	 * @param on {@link Boolean} value to set the annotaion's setting mode.
	 */
	private void setAnnotSettingMode(boolean on) {

		mEditEraserButton.setSelected(false);
		mEditNoteButton.setSelected(false);

		if (on) {
			((GradientDrawable) mAnnotSettingColorPickerButton.getBackground()).setColor(0xff000000 + AnnotSetting.instance().getLineColor(mAnnotToolType));
			mTopBarSwitcher.showNext();

			mController.changeGestureType(GestureType.EDIT);
			mController.setAnnotationTool(mAnnotToolType);

		} else {
			mTopBarSwitcher.showPrevious();

			mController.changeGestureType(GestureType.VIEW);
			mController.setAnnotationTool(AnnotToolType.NONE);

		}
	}

	/**
	 * Opens the edit mode.
	 */
	void editModeOn() {
		//mPageSlider.setVisibility(View.VISIBLE);
		setEditMode(true);
	}

	/**
	 * Closes the edit mode.
	 */
	void editModeOff() {
		//mPageSlider.setVisibility(View.INVISIBLE);
		mEditNoteButton.setSelected(false);
		mEditInkButton.setSelected(false);
		mEditEraserButton.setSelected(false);
		mEditHighlightButton.setSelected(false);
		mEditStrikeoutButton.setSelected(false);
		mEditUnderlineButton.setSelected(false);
		setEditMode(false);
	}

	/**
	 * Shows/hides the edit button.
	 *
	 * @param edit {@link Boolean} value to show/hide edit button.
	 */
	public void showEditButton(boolean edit) {

	}

	/**
	 * Enables/disables the PDF document's Outline button.
	 *
	 * @param show {@link Boolean} value to enable or disable the PDF document's Outline button.
	 */
	void showOutlineButton(boolean show) {

	}

	/**
	 * Saves the current state of the {@link Bundle} passed.
	 *
	 * @param state {@link Bundle} to save the current state.
	 */
	public void saveState(Bundle state) {
		if (!mButtonsVisible) {
			state.putBoolean("ButtonsHidden", true);
		}

		if (mTopBarIsSearch) {
			state.putBoolean("SearchMode", true);
		}
	}


	/**
	 * Restores the state from the passed-in {@link Bundle}
	 *
	 * @param state {@link Bundle}
	 */
	public void restoreState(Bundle state) {

		if (state == null || !state.getBoolean("ButtonsHidden", false)) {
			show();
		}

		if (state != null && state.getBoolean("SearchMode", false))
			searchModeOn();
	}

	/**
	 * Sets the display view mode in the horizontal direction.
	 */
	void setHorizontalMode() {
		/*mPageDisplayModeButton
				.setBackgroundResource(R.drawable.st_btn_view_mode_horizontal);*/
		mController.setPageDisplayMode(PageDisplayMode.HORIZONTAL);
	}

	/**
	 * Sets the display view mode in the bilateral vertical direction.
	 */
	void setBilateralVerticalMode() {
		mController.setPageDisplayMode(PageDisplayMode.BILATERAL_VERTICAL);
	}

	/**
	 * Sets the display view mode in the bilateral horizontal direction.
	 */
	void setBilateralHorizontalMode() {
		mController.setPageDisplayMode(PageDisplayMode.BILATERAL_HORIZONTAL);
	}

	/**
	 * Sets the display view mode with page flip effect by bilateral.
	 */
	void setBilateralRealisticMode() {
		mController.setPageDisplayMode(PageDisplayMode.BILATERAL_REALISTIC);
	}

	/**
	 * Sets the display view mode in the vertical direction.
	 */
	void setVerticalMode() {
		mController.setPageDisplayMode(PageDisplayMode.VERTICAL);
	}

	/**
	 * Sets the display view mode in the vertical direction.
	 */
	void setContinuosMode() {
		mController.setPageDisplayMode(PageDisplayMode.CONTINUOS);
	}

	/**
	 * Sets the preview display mode in each page.
	 */
	void setThumbnailMode() {
		mController.setPageDisplayMode(PageDisplayMode.THUMBNAIL);
	}

	/**
	 * Sets the display view mode with page flip effect.
	 */
	void setRealisticMode() {
		mController.setPageDisplayMode(PageDisplayMode.REALISTIC);
	}

	EditButtonClickHandler mEditButtonClickHandler = new EditButtonClickHandler();


	/**
	 * Edits the button click's event handler.
	 */
	private class EditButtonClickHandler implements View.OnClickListener{

		private boolean mLongClickEvented = false;

		@Override
		public void onClick(View v) {
			if (mLongClickEvented) {
				mLongClickEvented = false;
				return;
			}

			if(!mButtonsVisible) {
				return;
			}

			if (v.getId() == mEditInkButton.getId()) {

				mAnnotToolType = AnnotToolType.INK;
				setAnnotSettingMode(true);

			} else if (v.getId() == mEditHighlightButton.getId()) {

				mAnnotToolType = AnnotToolType.FREE_TEXT;
				setAnnotSettingMode(true);

			} else if (v.getId() == mEditUnderlineButton.getId()) {

				mAnnotToolType = AnnotToolType.UNDERLINE;
				setAnnotSettingMode(true);

			} else if (v.getId() == mEditStrikeoutButton.getId()) {

				mAnnotToolType = AnnotToolType.STRIKEOUT;
				setAnnotSettingMode(true);

			} else if (v.getId() == mEditNoteButton.getId()) {

				mEditNoteButton.setSelected(!mEditNoteButton.isSelected());
				if (mEditNoteButton.isSelected()) {
					mController.changeGestureType(GestureType.EDIT);
					mController.setAnnotationTool(AnnotToolType.NOTE);
				} else {
					mController.changeGestureType(GestureType.VIEW);
					mController.setAnnotationTool(AnnotToolType.NONE);
				}

			} else if (v.getId() == mEditEraserButton.getId()) {

				mEditEraserButton.setSelected(!mEditEraserButton.isSelected());
				if (mEditEraserButton.isSelected()) {
					mController.changeGestureType(GestureType.EDIT);
					mController.setAnnotationTool(AnnotToolType.ERASER);
				} else {
					mController.changeGestureType(GestureType.VIEW);
					mController.setAnnotationTool(AnnotToolType.NONE);
				}

			} else if (v.getId() == mAnnotToolSelectButton.getId()) {
				mAnnotToolSelectMenu.show(v, 0, 0);
				setAnnotSettingMode(true);
			}
		}
	}

	/**
	 * Shows/hides the provided {@link Button} with respect to the given boolean value.
	 *
	 * @param button {@link Button} to show/hide
	 * @param enable {@link Boolean} value to enable or disable the {@link Button}
	 */
	private void enableAnnotButton(Button button, boolean enable) {
		if (enable) {
			button.setVisibility(View.VISIBLE);
		} else {
			button.setVisibility(View.GONE);
		}
	}

	/**
	 * Enables the annotation feature (Ink/Link/Note).
	 *
	 * @param types {@link String} value which enables the annotation feature.
	 * @param enable {@link Boolean} value to show/hide the annotation button.
	 */
	public void enableAnnotFeature(String types, boolean enable) {
		// INK, LINK, NOTE
		String targets[] = types.split(":");
		for (String target : targets) {
			if (target.equals("INK")) {
				enableAnnotButton(mEditInkButton, enable);
			} else if (target.equals("NOTE")) {
				enableAnnotButton(mEditNoteButton, enable);
			} else if (target.equals("LINK")) {
			}
		}

		if (mEditInkButton.getVisibility() == View.VISIBLE
				|| mEditNoteButton.getVisibility() == View.VISIBLE) {
			enableAnnotButton(mEditEraserButton, true);
		} else {
			enableAnnotButton(mEditEraserButton, false);
		}
	}

	public boolean isEnableHiddenTopBar() {
		return enableHiddenTopBar;
	}

	public void setEnableHiddenTopBar(boolean enableHiddenTopBar) {
		this.enableHiddenTopBar = enableHiddenTopBar;
	}

	public boolean isEnableHiddenBottomBar() {
		return enableHiddenBottomBar;
	}

	public void setEnableHiddenBottomBar(boolean enableHiddenBottomBar) {
		this.enableHiddenBottomBar = enableHiddenBottomBar;
	}

	@Override
	protected void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		mControlPanel.refreshLayout();
	}

	protected void setNumberOfPreView(int numberOfPreView){
		if(numberOfPreView <= 0) mNumberOfPreView = 0;
		else if(numberOfPreView >= 4) mNumberOfPreView = 4;
		else mNumberOfPreView = numberOfPreView;
	}
}
